package com.jsits.v2x.common.connection.socket;

import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Date;

public abstract class SocketClient extends SocketBase
{
	/**
	 * 日志
	 */
	private static Logger logger = LoggerFactory.getLogger(SocketClient.class);
	
	/**
	 * mina客户端与服务端建立的连接信息
	 */
	protected IoConnector connector;
	
	/**
	 * 客户端与服务端连接成功后的session信息
	 */
	protected IoSession session;

	/**
	 * 最大缓冲区长度
	 */
	public static final int MAX_BUFFER_SIZE = 1024 * 1024;
	
	/**
	 * 与服务端建立连接
	 * @see SocketBase#connectServer()
	 *  0.连接成功 1.拒绝连接 2.连接失败
	 */
	protected Integer connectServer()
	{
		Integer retValue = 0;
		ConnectFuture connFuture = null;
		try 
		{
			connector = new NioSocketConnector();
			//设置消息的编解码
			SocketFactory factory = new SocketFactory();
			factory.setSocketBase(this);
			connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(factory));
			//设置消息
			MessageHandler messageHandle = new MessageHandler();
			messageHandle.setSocketBase(this);
			connector.setHandler(messageHandle);
			//设置客户端连接属性
			connector.getSessionConfig().setUseReadOperation(true);
			connector.getSessionConfig().setMaxReadBufferSize(MAX_BUFFER_SIZE);
			connector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 15); //设置session的空闲超时时间
			
			//与服务端建立连接
			connFuture = connector.connect(new InetSocketAddress(serverInfo.getIp(), serverInfo.getPort()));
			connFuture.awaitUninterruptibly();
			//获取连接Session
			session = connFuture.getSession();
			
			if(connFuture.isConnected()) 
			{
				serverInfo.setStatus(true);
				serverInfo.setTimeStamp(new Date().getTime());
				logger.info("Create socket connect with server success, ip: " + serverInfo.getIp() + ", port: " + serverInfo.getPort());
				retValue = 0;
				return retValue;
			}
			else
			{
				//session.close(true);
				session.closeNow().setClosed();
				connector.dispose();
				logger.error("Create socket connect with server failed, ip: " + serverInfo.getIp() + ", port: " + serverInfo.getPort());
				retValue = 2;
			}
		}
		catch (Exception e) 
		{
			if (("Connection refused: no further information").equals(e.getCause().getMessage())) {
				logger.error("Create socket connect with server refused, ip: " + serverInfo.getIp() + ", port: " + serverInfo.getPort());
				retValue = 1;
			} else {
				logger.error("Create socket connect with server failed In exception, ip: " + serverInfo.getIp() + ", port: " + serverInfo.getPort());
				retValue = 2;
			}
			if (session != null) session.closeNow().setClosed();
			if (connector != null) connector.dispose();
			//if (connFuture != null) ((DefaultIoFuture)connFuture).setValue(Boolean.TRUE);

		}
		
		return retValue;
	}
	
	/**
	 * 断开与服务端的连接
	 * @see SocketBase#disConnectServer()
	 */
	protected CloseFuture disConnectServer()
	{

		//session.getCloseFuture().setClosed();
		//session.close(true);
		CloseFuture closeFuture = session.closeNow();
		closeFuture.setClosed();
		connector.dispose();
		return closeFuture;
	}
	
	/**
	 * 发送消息至服务端
	 * @see SocketBase#sendMessage(SocketMessage, org.apache.mina.core.session.IoSession)
	 */
	public void sendMessage(SocketMessage message, IoSession session)
	{
		//将消息写入Session，在MessageEncoder中会对消息进行编码并发送至服务端
		this.session.write(message);
	}

}
